import * as THREE from "three";
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
//引入性能监视器stats.js
import Stats from "three/addons/libs/stats.module.js";

const stats = new Stats();

// stats.domElement显示：渲染帧率  刷新频率,一秒渲染次数
// stats.setMode(0);//默认模式
//stats.domElement显示：渲染周期 渲染一帧多长时间(单位：毫秒ms)
stats.setMode(1);

const scene = new THREE.Scene();

// 正投影相机
const width = window.innerWidth; //canvas画布宽度
const height = window.innerHeight; //canvas画布高度
const k = width / height; //canvas画布宽高比
const s = 50; //控制left, right, top, bottom范围大小
const camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 8000);
camera.position.set(300, 300, 300); 
// camera.lookAt(0, 0, 0); //指向坐标原点




// 透视相机
// const camera = new THREE.PerspectiveCamera(
//   45,
//   window.innerWidth / window.innerHeight,
//   0.1,
//   1000
// );
// 设置相机的位置以便更好地查看线段
// camera.position.z = 100;
// camera.position.y = 100;
// camera.position.x = 100;

const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

// ------------------------------------------------
// const geometry = new THREE.BoxGeometry(200, 200, 200);
// const material = new THREE.MeshLambertMaterial({
//   color: 0xeeffff, //设置材质颜色
// });
// // 混合几何 材质 生成网状mesh
// const mesh = new THREE.Mesh(geometry, material);
// // 设置模型mesh的xyz坐标
// mesh.position.set(0, 0, 0);
// //场景添加mesh
// scene.add(mesh);

// const box3 = new THREE.Box3()
// console.log('box3',box3);
// // box3.min = new THREE.Vector3(-10, -10,0);
// // box3.max = new THREE.Vector3(100, 20,50);

// box3.expandByObject(mesh); // 计算模型包围盒
// console.log('查看包围盒',box3);

// const scale = new THREE.Vector3()
// // getSize()计算包围盒尺寸
// // 获得包围盒长宽高尺寸，结果保存在参数三维向量对象scale中
// box3.getSize(scale)
// console.log('模型包围盒尺寸', scale);

// const center = new THREE.Vector3()
// box3.getCenter(center)
// console.log('模型中心坐标', center);

const data = [
  [20, 20],
  [40, 0],
  [20, -20],
  [0, -20],
  [-20, -20],
  [-40, 0],
  [-20, 20]
]
const pointsArr = [];// 一组二维向量表示一个多边形轮廓坐标
data.forEach(function(e){
    // data坐标数据转化为Vector2构成的顶点数组
    const v2 = new THREE.Vector2(e[0],e[1])
    pointsArr.push(v2);
})
// Shape表示一个平面多边形轮廓,参数是二维向量构成的数组pointsArr
const shape = new THREE.Shape(pointsArr);
// 多边形shape轮廓作为ShapeGeometry参数，生成一个多边形平面几何体

const geometry = new THREE.ShapeGeometry(shape);

const material = new THREE.MeshLambertMaterial({
  side: THREE.FrontSide, //双面显示看到管道内壁
  color: 0x00ffff,
});
const line = new THREE.LineLoop(geometry, material);//线条模型对象

scene.add(line)


// 包围盒计算模型对象的大小和位置
const box3 = new THREE.Box3();
box3.expandByObject(line); // 计算模型包围盒
const size = new THREE.Vector3();
box3.getSize(size); // 计算包围盒尺寸
// console.log('模型包围盒尺寸',size);
const center = new THREE.Vector3();
box3.getCenter(center); // 计算包围盒中心坐标
console.log('模型中心坐标',center);
camera.lookAt(center); //指向坐标原点



console.log('.up默认值',camera.up);
// camera.up.set(0,-1,0)




// const material = new THREE.MeshLambertMaterial({
//   side: THREE.FrontSide, //双面显示看到管道内壁
//   color: 0x00ffff,
// });
// // THREE.FrontSide 仅渲染几何体的正面。这是默认行为，意味着只有当观察者从多边形顶点按照顺时针顺序定义的那一面看过去时，才能看到材质。
// // THREE.BackSide ：仅渲染几何体的背面。这意味着只有当观察者从多边形顶点按照逆时针顺序定义的那一面看过去时，才能看到材质
// // THREE.DoubleSide ：同时渲染几何体的正面和背面。这对于创建诸如窗户、纸张等双面都可见的对象非常有用。
// const line = new THREE.Mesh(geometry, material);

// scene.add(line);
// -----------------------------------------------

// 渲染循环
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}
animate();

const axesHelper = new THREE.AxesHelper(300);

// 添加辅助坐标系
scene.add(axesHelper);

// width和height用来设置Three.js输出的Canvas画布尺寸(像素px)
// const width = window.innerWidth; //窗口文档显示区的宽度作为画布宽度
// const height = window.innerHeight; //窗口文档显示区的高度作为画布高度

//点光源：两个参数分别表示光源颜色和光照强度
const pointLight = new THREE.PointLight(0xffffff, 1.0);
pointLight.decay = 1.0; //设置光源距离衰减

// 你可以对比不同光照强度明暗差异(传播同样距离)
pointLight.intensity = 100.0; //光照强度
// pointLight.intensity = 50000.0;//光照强度

//点光源位置 ,放在x轴上
// pointLight.position.set(0, 400, 400);
// pointLight.position.set(100, 60, 50);
pointLight.position.set(100, 50, 75);

//点光源添加到场景中
// scene.add(pointLight);

// 光源辅助观察
// const pointLightHelper = new THREE.PointLightHelper(pointLight, 10);
// scene.add(pointLightHelper);

//环境光:没有特定方向，整体改变场景的光照明暗
const ambient = new THREE.AmbientLight(0xffffff, 0.1);
scene.add(ambient);

// 平行光
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
// 设置光源的方向：通过光源position属性和目标指向对象的position属性计算
directionalLight.position.set(80, 100, 50);


// 设置相机控件轨道控制器OrbitControls
const controls = new OrbitControls(camera, renderer.domElement);
// 启用阻尼效果
controls.enableDamping = true;
controls.dampingFactor = 0.05;

// 如果OrbitControls改变了相机参数，重新调用渲染器渲染三维场景
controls.addEventListener("change", function () {
  renderer.render(scene, camera); //执行渲染操作
  // 浏览器控制台查看相机位置变化
  // console.log("camera.position", camera.position);
});

//执行渲染操作
renderer.render(scene, camera);

// Canvas画布插入到任意HTML元素中
// document.getElementById("webgl").appendChild(renderer.domElement);

document.body.appendChild(renderer.domElement);
document.body.appendChild(stats.domElement);

// let angle = 0; //用于圆周运动计算的角度值
// const R = 100; //相机圆周运动的半径


// 渲染函数
function render() {
  // camera.position.z -= 0.3;//相机直线运动动画
  // angle += 0.01;
  // 相机y坐标不变，在XOZ平面上做圆周运动
  // camera.position.x = R * Math.cos(angle);
  // camera.position.z = R * Math.sin(angle);
  // .position改变，重新执行lookAt(0,0,0)计算相机视线方向
  // camera.lookAt(0,0,0);

  renderer.render(scene, camera); //执行渲染操作
  // mesh.rotateY(0.01); //每次绕y轴旋转0.01弧度
  controls.update(); // 必须调用此方法，以便阻尼效果生效
  stats.update(); //requestAnimationFrame循环调用的函数中调用方法update(),来刷新时间
  requestAnimationFrame(render); //请求再次执行渲染函数render，渲染下一帧
}
render();

window.onresize = function () {
  // // 重置渲染器输出画布canvas尺寸
  // renderer.setSize(window.innerWidth, window.innerHeight);
  // // 全屏情况下：设置观察范围长宽比aspect为窗口宽高比
  // camera.aspect = window.innerWidth / window.innerHeight;
  // 渲染器执行render方法的时候会读取相机对象的投影矩阵属性projectionMatrix
  // 但是不会每渲染一帧，就通过相机的属性计算投影矩阵(节约计算资源)
  // 如果相机的一些属性发生了变化，需要执行updateProjectionMatrix ()方法更新相机的投影矩阵
  const width = window.innerWidth; //canvas画布宽度
  const height = window.innerHeight; //canvas画布高度
  // 1. WebGL渲染器渲染的Cnavas画布尺寸更新
  renderer.setSize(width, height);
  // 2.1.更新相机参数
  const k = width / height; //canvas画布宽高比
  camera.left = -s*k;
  camera.right = s*k;
  // 2.2.相机的left, right, top, bottom属性变化了，通知threejs系统
  camera.updateProjectionMatrix();


};

// console.log(THREE);
